home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 21 / QRZ Ham Radio Callsign Database - Volume 21.iso / DEVELOP / QRZTECH.TXT < prev   
Text File  |  2001-11-01  |  14KB  |  312 lines

  1.  
  2. The QRZ! Ham Radio CDROM 
  3. Callsign Database Technical Specification         Rev D October 2001
  4.  
  5.  
  6. The following information is provided for developers who wish to write
  7. their own software to directly access the QRZ callsign database files.
  8. Windows programmers including Visual C++ and Visual Basic users should
  9. refer to the help file called QRZDLL.HLP which documents database
  10. access through our custom dynamic link libraries, QRZDLL.DLL (for win3)
  11. and QRZ32.DLL (for Win95/98/ME/2000/NT).
  12.  
  13. Users of the QRZ! Ham Radio CDROM who wish to write their own callsign
  14. database search and retrieval software are encouraged to do so.  We
  15. welcome user contributed shareware programs for future versions of the
  16. QRZ! Ham Radio CDROM.
  17.  
  18.  
  19. Overview
  20.  
  21. There are three versions of the QRZ software for the PC, all of
  22. which share a common architecture.  Separate versions are provided
  23. for DOS, Windows 3.1 and Windows 95 and/or Windows NT.  All of the
  24. programs access the database using the same method.
  25.  
  26. The QRZ callsign database indexing and retrieval method was designed
  27. and optimized for CDROM use.  The primary goal was to provide fast
  28. searches for the most commonly sought after information.  A key to this
  29. strategy is the caching of index information in memory to minimize
  30. reads and more importantly, seeks from the CDROM drive.  The method
  31. described below implements one such strategy and has been shown to
  32. require only one CDROM head seek per database lookup.
  33.  
  34.  
  35. Database Structure
  36.  
  37. The QRZ callsign database is composed of four separate copies of the
  38. data, and four indices, each of which is sorted by different criteria.
  39. One copy is sorted by callsign, one by last name, one by city/state and
  40. one by zip code.  Due to differences in the way foreign addresses are
  41. represented, many DX countries are not represented in the City/State
  42. and Zip code databases.  These countries are generally searchable by
  43. callsign and/or name only.
  44.  
  45.  
  46. Data file    Index file    Database type
  47. -----------------------------------------------------
  48. callbkc.dat    callbkc.idx    Callsign
  49. callbkn.dat    callbkn.idx    Name
  50. callbks.dat    callbks.idx    State and City
  51. callbkz.dat    callbkz.idx    Zip Code
  52.  
  53.  
  54. All of the database files are located in the directory \CALLBK on the
  55. CDROM.  Each of the four datafiles (*.dat) is accompanied by a
  56. corresponding index file (*.idx).  The index files contain selected
  57. keys from their corresponding databases which were selected by sampling
  58. the databases at regular file offset intervals.  The sampling intervals
  59. are chosen to produce indices that are no more than 64 Kbytes in length
  60. so that they can each be contained within 64 Kb memory segments under
  61. DOS and Window 3.x.  The same indices are used in the Win32 environment
  62. despite the fact that there are no 64 Kbyte segment constraints, to
  63. preserve compatibility with Win3 and DOS programs.
  64.  
  65. The sampling interval for the index keys is subject to change from
  66. one release of the QRZ CDROM to the next and is therefore recorded
  67. as one of the critical operating parameters in the header of each
  68. index file.  This value, referred to as BytesPerKey, must be treated
  69. by your program as dynamic and must be fetched from each of the
  70. index headers at the start of each session.  A different BytesPerKey
  71. values is used for each database.
  72.  
  73. The index header occupies the first 48 bytes of the *.idx file and
  74. has the following format:
  75.  
  76. /*
  77. **     Index Header Block Definition (Version 2)
  78. **     (applies to all QRZ CDROMS from Version 2 onward) 
  79. **
  80. **     This block is located at the start of each index file
  81. */
  82. typedef struct {
  83.   char  DataName[16];    /* Name of the data file            */
  84.   char  BytesPerKey[8];  /* Data Bytes per Index Item        */
  85.   char  NumKeys[8];      /* Number of items in this index    */
  86.   char  KeyLen[8];       /* Length of each key item in bytes */
  87.   char  Version[8];      /* Database Version ID              */
  88. } index_header;
  89.  
  90. All values in the index header block are stored in ASCII character 
  91. representation.  These characters must be converted (by your program)
  92. into string or integer values as necessary.  Characters are left
  93. justified within each field and unused field characters (if any)
  94. are zero filled.  Your program should not depend on the presence of
  95. the null characters when reading these fields since some values could
  96. legitimately fill the entire field.
  97.  
  98.  
  99. Index Data Formats
  100.  
  101. Some number of keys (noted by the NumKeys field) immediately follow the
  102. index header block in the index file.  All fields in a given index
  103. file will have a width (in bytes) of 'KeyLen'.
  104.  
  105. The name index (CALLBKN.IDX) uses uniform keys which are set to a
  106. maximum of 'KeyLen' characters per name.  Longer names are simply
  107. truncated.  Names are stored in last-first format with a space between
  108. the two parts.  The city/state index (CALLBKC) also uses 'KeyLen'
  109. characters per entry with the two character state code occupying the
  110. first two characters and the city name in the last 10 characters.  For
  111. example, the town of Fremont, CA is represented as CAFREMONT in the
  112. index.  Callsigns (in CALLBKC.IDX) each occupy a different 'KeyLen'
  113. width slot (typically 6 characters wide) and zip code indices
  114. (CALLBKZ.IDX) do the same using a typical KeyLen value of 5.  Your
  115. program must always interpret KeyLen, BytesPerKey, and NumKeys and
  116. never make assumptions regarding their sizes.  These sizes could change
  117. in a future edition of the database and your program must be prepared
  118. to deal with it.
  119.  
  120.  
  121. Using the Index Header Block
  122.  
  123. The header block describes the field data which immediately follows
  124. it.  The records are tightly packed on 'BytesPerKey' boundaries without
  125. separators making them ideal candidates for use as memory arrays.
  126. Although unused key fields will be zero filled to the right, there is
  127. no guarantee that any given field will be null terminated.  Because of
  128. this, the indices must always be searched in a random access, fixed
  129. record length format.
  130.  
  131. A typical program will first search for the system drive that contains
  132. the \CALLBK base directory.  Next, the program will open and load each
  133. of the four indices into four separate 64 Kb memory buffers.  Searching
  134. the indices is then performed by addressing the buffers as one-dimensional
  135. arrays which contain 'NumKeys' elements that are each 'KeyLen' bytes wide.
  136.  
  137. A search for a particular item starts with the user inputting a desired
  138. key which is then formatted into an index key value.  The program then
  139. uses this key value to locate the closest match in the index table
  140. which is less than or equal to the the user supplied key.  For most
  141. machines a simple linear search of the table will be fast enough
  142. however a binary search algorithm can be employed.
  143.  
  144. After the relevant table key is chosen, it's ordinal position from the
  145. start of the table is saved in a variable called KeyOffset.  Next, the
  146. program must multiply the KeyOffset value by the BytesPerKey value
  147. which yields a DataOffset value.  This DataOffset value is then used as
  148. an index into the actual datafile (*.dat).
  149.  
  150. Typically, a program will use the DataOffset value as an argument to a
  151. File Seek system call ( fseek() ).  Once the file pointer is positioned
  152. at the DataOffset, the program can then begin a linear search for the
  153. desired record in the database.  Again, a binary search between the
  154. [DataOffset] and [KeyOffset+1*BytesPerKey] can be used however experience
  155. has shown this will provide only a minimal improvement in performance.
  156.  
  157. Be aware that the derived DataOffset value will usually land you in the
  158. middle of some record.  This is typical and you will find that the
  159. callsign that was pointed to by the index key will be located at the
  160. beginning of the next text line in the file.  The data file is an
  161. ordinary ASCII text file with a single newline (0x0a) character at
  162. the end of each line.
  163.  
  164. The search of the data file should terminate at offset
  165. [KeyOffset+1 * BytesPerKey] if the desired record has not yet been found.
  166.  
  167.  
  168. Database Format
  169.  
  170. The database files all have the same format.  They are ASCII files
  171. which consist of one text line per record.  Each record consists of a
  172. fixed number of comma separated fields with blank fields represented by
  173. consecutive commas.  Each line is terminated with a single ASCII
  174. newline ('\n', 0x0a, or chr$(10)) character.
  175.  
  176. Every record has the same number of commas in it, except for
  177. cross-reference records, which are discussed below.  If the data itself
  178. is supposed to contain a comma, then it is represented in the database
  179. by a semi-colon ';' which should be replaced by a comma in the program's
  180. text output formatting routine.
  181.  
  182.  
  183. Here's an example of one record from the database:
  184.  
  185. AA7BQ ,LLOYD,,FRED L,,53340,90009,00009,8215 E WOOD DR,SCOTTSDALE,AZ,
  186. 85260,E,KJ6RK,A
  187.  
  188. /*
  189. **    Standard Record Field Offsets
  190. */
  191. #define Callsign        0       AA7BQ
  192. #define LastName        1       LLOYD
  193. #define Email/Country   2       .271 *
  194. #define FirstName       3       FRED L
  195. #define JPG             4       . *
  196. #define DateOfBirth     5       53340        // Dec 6, 1953
  197. #define EffectiveDate   6       90009        // Jan 9, 1990
  198. #define ExpirationDate  7       00009        // Jan 9, 2000
  199. #define MailStreet      8       8215 E. Wood DR
  200. #define MailCity        9       SCOTTSDALE
  201. #define MailState       10      AZ
  202. #define ZipCode         11      85260 
  203. #define LicenseClass    12      E        // (P = TechPlus)
  204. #define PreviousCall    13      KJ6RK 
  205. #define PreviousClass   14      A 
  206.  
  207.  
  208. * The fields Email/Country and JPG are used to indicate various flags
  209. and modifiers to the record.
  210.  
  211. Email/Country indicates a) whether an email address exists for this
  212. record, and b) the country number of the specified address.  If an
  213. email address exists for this record (i.e. a corresponding address
  214. exists in the netaddr.qrz database), then the FIRST character of this
  215. field will contain a period (.).  Following the period, or first in
  216. this field if no period is present, is the country number that
  217. corresponds to this record.
  218.  
  219. Country numbers may be directly cross referenced in the ASCII text file
  220. called COUNTRIES.DAT, located in the database directiory.
  221.  
  222. The JPG field indicates whether this callsign has a JPG image on this
  223. CDROM.  If present, the image will be located in the E:\CALLBK\GIFS
  224. directory (assuming E: is the CDROM drive).
  225.  
  226. Note: The email database netaddr.qrz is proprietary and is not
  227. documented or accessible to user-developed programs.  Access routines
  228. are provided to C++ and Visual Basic users through the QRZ DLL's.
  229.  
  230.  
  231. Callsign Collating Sequence
  232.  
  233. Callsigns in the QRZ databases are stored in a special columnar format
  234. which aids in performing searches.  With this format, the area digit
  235. part of the callsign is always in the same position.  Callsigns are
  236. considered to have a prefix, an area number and a suffix.  Collating
  237. preference is always given in reverse order, that is, suffix followed
  238. by area number followed by prefix.  When callsigns are compared for
  239. sorting and searching, a this collating sequence (called 'defcab') is
  240. applied to the callsign which results in the following logical behavior:
  241.  
  242.  
  243.          abcdef  sort order  reason
  244.     -------- ---------- ---------
  245.     "KB3A  "    1st       def
  246.         "KB2AB "    2nd       defc
  247.     "K 5AB "    3rd       def
  248.         "KB1ABC"    4th       defc
  249.     "K 4ABC"    5th       defca
  250.     "WA4ABC"    6th       defcab
  251.     "WB4ABC"    7th 
  252.  
  253.  
  254. The 'reason' lists why each entry deserves its position in the list
  255. above the one below it.
  256.  
  257. To compare two callsigns for greater than, less than or equality, the
  258. program must first transpose them into 'defcab' format (using spaces
  259. for unused positions) and then do a left-to-right comparison of the two.
  260. For example, to compare K1ABC against KC8AB, the program would do the
  261. following:
  262.                                   defcab
  263. callsign K1ABC is transposed to: "ABC1K "
  264. callsign KB8AB is transposed to: "AB 8KC"
  265.  
  266. then, a string compare as in:    strcmp("ABC1K ", "AB 8KB")
  267.  
  268. will return a "greater than" value meaning that K1ABC comes _after_
  269. KB8AB in the database having been found greater at point 'f' in the
  270. defcab sequence.
  271.  
  272.  
  273. Date Formats
  274.  
  275. All dates are stored in 5 character Julian format, e.g. 93003 equals
  276. January 3, 1993 or the 3rd day of 1993.  Dates before 1900 or after
  277. year 2000 must be determined by the context in which they are used.
  278. In other words, if the resultant age does not make sense, then it is
  279. wrong.  For example, all licenses expire in the future so for license
  280. expiration dates 02 must mean 2002.  Birthdays are more difficult to
  281. judge but most can be arbitrarily considered to be greater than 10
  282. years old.  This is not a perfect method, but it does yield
  283. satisfactory overall results.
  284.  
  285.  
  286. Cross Reference Information
  287.  
  288. When the FCC supplies a "previous callsign" in their database, it
  289. is used by QRZ to construct a cross reference so that a person can
  290. be found by their old call as well as their new one.
  291.  
  292. A cross reference record is distinguished from other records as one
  293. which contains only one comma.  A cross-reference record takes the
  294. form of "OldCall,NewCall" with no other information on the line.
  295.  
  296. When a cross reference record is encountered, your program must fetch
  297. the second field and restart the search from the beginning to return
  298. the primary reference.
  299.  
  300.  
  301.  
  302. -------------------------------------------------------------------
  303.  
  304. Please address programming questions and/or comments to:
  305.  
  306. flloyd@qrz.com
  307.  
  308. -------------------------------------------------------------------
  309.  
  310. Fred Lloyd, AA7BQ   10/23/01
  311.  
  312.